using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.ESG.Entities;
using Sustainalytics.Synchronization.Validation.Handlers.Common;
using Sustainalytics.Synchronization.Validation.Handlers.Comprehensive;
using Sustainalytics.Synchronization.Validation.Internals;
using Sustainalytics.Synchronization.Validation.ValidationRules.Comprehensive;
using Sustainalytics.Synchronization.Validation.Validators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Sustainalytics.Synchronization.Validation.Tests.IntegrationTest
{
    public class RulesIntegrationTest
    {

        private readonly ITestOutputHelper outputHelper;

        private const string TestMongo = "54.72.160.155";

        private readonly string currentDatabase = string.Format($"mongodb://{TestMongo}:27017/ClientDW_A");
        private readonly string previousDatabase = string.Format($"mongodb://{TestMongo}:27017/ClientDW_B");
        private const string Collection = "ClientDW";

        private readonly ComprehensiveCompanies esgCompanies = new ComprehensiveCompanies();

        private IHandler sut;

        public RulesIntegrationTest(ITestOutputHelper outputHelper)
        {
            esgCompanies.AddRange(
                MongoDB.Extensions.MongoFactory.GetCollectionFromDatabase<CorporateData>(currentDatabase)
                    .Find(Builders<CorporateData>.Filter.Where(c => c.ComprehensiveEsgResearchState.ResearchState == ResearchState.ResearchAvailable))
                    .Project(x => x.Id)
                    .ToList());

            this.outputHelper = outputHelper;

        }


        public class FeedBackRequestedRuleTests : RulesIntegrationTest
        {
            public FeedBackRequestedRuleTests(ITestOutputHelper outputHelper) : base(outputHelper)
            {
                sut = new ComprehensiveRpCompanyProfileHandler(esgCompanies,
              ValidationMongoCollectionFactory.GetCollectionFromDatabase<RPCompanyProfile>(
                  new Dictionary<string, string> { { Collection, currentDatabase } },
                  new Dictionary<string, string> { { Collection, previousDatabase } },
                  x => x[Collection]),
              new ComprehensiveValidator<RPCompanyProfile>(
                  new List<ComprehensiveRule<RPCompanyProfile>> { new FeedbackRequestedRule() }));

            }

            [Fact]
            public async Task FeedBackMinValue()
            {
                var validationResult = new List<Guid>();
                await sut.ForEachElementsAsync(
                        result => { validationResult.AddRange(result.ValidationErrors.Select(error => error.Key)); })
                    .ConfigureAwait(false);

                foreach (var result in validationResult)
                    outputHelper.WriteLine(result.ToString());
            }
        }

        public class OverallScoreRulesTests : RulesIntegrationTest
        {
            [Fact]
            public async Task OverallScoreuleHandler()
            {
                var validationResult = new List<Guid>();
                await sut.ForEachElementsAsync(
                        result => { validationResult.AddRange(result.ValidationErrors.Select(error => error.Key)); })
                    .ConfigureAwait(false);

                foreach (var result in validationResult)
                    outputHelper.WriteLine(result.ToString());
            }

            public OverallScoreRulesTests(ITestOutputHelper outputHelper) : base(outputHelper)
            {
                sut = new CompanyComputationResultHandler(
                esgCompanies,
                ValidationMongoCollectionFactory.GetCollectionFromDatabase<RPCompanyESGComputationResult>(
                    new Dictionary<string, string> { { Collection, currentDatabase } },
                    new Dictionary<string, string> { { Collection, previousDatabase } },
                    x => x[Collection]),
                new ComprehensiveValidator<RPCompanyESGComputationResult>(
                    new List<ComprehensiveRule<RPCompanyESGComputationResult>> { new ScoreChangeRedRule() }));
            }
        }

        public class HighestControversyScoreChangeTest : RulesIntegrationTest
        {
            public HighestControversyScoreChangeTest(ITestOutputHelper outputHelper) : base(outputHelper)
            {
                sut = new RPControversyIndicatorHandler(esgCompanies,
               ValidationMongoCollectionFactory.GetCollectionFromDatabase<RPControversyIndicator>(
                   new Dictionary<string, string> { { Collection, currentDatabase } },
                   new Dictionary<string, string> { { Collection, previousDatabase } },
                   x => x[Collection]),
               new ComprehensiveValidator<RPControversyIndicator>(
                   new List<ComprehensiveRule<RPControversyIndicator>> { new ControversyChangeRule() }));
            }

            [Fact]
            public async Task HighestControversyScoreHandlerTest()
            {
                var validationResult = new List<Guid>();
                await sut.ForEachElementsAsync(
                        result => { validationResult.AddRange(result.ValidationErrors.Select(error => error.Key)); })
                    .ConfigureAwait(false);

                foreach (var result in validationResult)
                    outputHelper.WriteLine(result.ToString());
            }
        }
    }
}